home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 2 / Meeting Pearls Vol. II (1995)(GTI - Schatztruhe)[!].iso / Pearls / arc / XFH / src / CFS.c < prev    next >
C/C++ Source or Header  |  1994-04-23  |  32KB  |  1,158 lines

  1. /* CFS.c - main packet loop.
  2.    Copyright (C) 1991, 1992, 1993, 1994 Kristian Nielsen.
  3.  
  4.    This file is part of XFH, the compressing file system handler.
  5.  
  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2 of the License, or
  9.    (at your option) any later version.
  10.  
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.            */
  19.  
  20. /* This file replaces the startup code! Make sure the object file
  21.  * corresponding to this source is linked into the head of the final
  22.  * executeable.
  23.  */
  24.  
  25. #include "CFS.h"
  26.  
  27. #include <exec/ports.h>
  28. #include <exec/memory.h>
  29. #include <exec/execbase.h>
  30.  
  31. #include <clib/alib_protos.h>
  32.  
  33. #include <string.h>
  34. #include <stdarg.h>
  35.  
  36. #include <dossupport.h>
  37.  
  38. struct ExecBase *SysBase;
  39. struct DosLibrary *DOSBase;
  40.  
  41. char Version[]   = "$VER: XFH-Handler " VERSION " " __AMIGADATE__ "";
  42. char Copyright[] = "$COPYRIGHT: Copyright (C) 1991, 1992, 1993, 1994 Kristian Nielsen";
  43.  
  44. /**************************************************************************
  45.  *                                                                        *
  46.  * Handler entry point.                                                   *
  47.  *                                                                        *
  48.  * Do initialisation and allocation, then enter main loop after returning *
  49.  *    our initial packet.                                                 *
  50.  *                                                                        *
  51.  **************************************************************************/
  52.  
  53. LONG __saveds NotReallyMain(void)
  54.  
  55. {
  56.  glb glob;
  57.  struct DosPacket *pkt;
  58.  int ret=0;
  59.  struct FileLock *parent;
  60.  void handle_packet(glb glob, struct DosPacket *pkt);
  61.    
  62.  SysBase=*(struct ExecBase **)4L;
  63.  if ((glob=AllocMem(sizeof(struct glob),MEMF_CLEAR))==NULL) return(100);
  64.  
  65.  glob->ioerr=ERROR_ACTION_NOT_KNOWN;  /* Default error code. */
  66.  
  67.  debug (("XFH/CFS compressing file system handler v" VERSION ".\n"
  68.         "Copyright (C) 1991,1992,1993 Kristian Nielsen.\n"));
  69.  debug (("Starting handler with task at 0x%lx.\n",FindTask(0L)));
  70.  
  71.  glob->dosport=&(glob->myproc=(struct Process *)(glob->mytask=FindTask(0L)))->pr_MsgPort;
  72.  
  73.  pkt=getpkt(glob);
  74.  glob->devnode=(struct DeviceNode *)b2c(pkt->dp_Arg3);
  75.  if (glob->devnode->dn_Name==NULL)
  76.   {
  77.    debug (("Error: NULL device name - exiting.\n"));
  78.    glob->ioerr=ERROR_INVALID_COMPONENT_NAME;
  79.    returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
  80.    ret=100;
  81.    goto exitthis;
  82.   }
  83.  
  84.  if ((glob->devname=copybstr(glob->devnode->dn_Name))==NULL)
  85.   {
  86.    debug (("Error copying device name - exiting.\n"));
  87.    OUTOFMEM;
  88.    returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
  89.    ret=100;
  90.    goto exitthis;
  91.   }
  92.  if (glob->devname[0]=='\0')
  93.   {
  94.    debug (("Error: Empty device name - exiting.\n"));
  95.    glob->ioerr=ERROR_INVALID_COMPONENT_NAME;
  96.    returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
  97.    ret=100;
  98.    goto exitthis;
  99.   }
  100.  
  101.  debug (("Using device name '%s'.\n",glob->devname));
  102.  
  103.  glob->bcplstartup=glob->devnode->dn_Startup;
  104.    
  105.  if ((glob->ioport=CreatePort(NULL,0L))==NULL)
  106.   {
  107.    OUTOFMEM;
  108.    returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
  109.    ret=100;
  110.    debug (("Error creating message port - exiting.\n"));
  111.    goto exitthis;
  112.   }
  113.  
  114.  if ((glob->DOSBase=OpenLibrary("dos.library",0L))==NULL)
  115.   {
  116.    glob->ioerr=ERROR_INVALID_RESIDENT_LIBRARY;
  117.    returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
  118.    debug (("Error opening dos.library - exiting.\n"));
  119.    ret=100;
  120.    goto exitthis;
  121.   }
  122.    DOSBase=glob->DOSBase;
  123.  
  124.  /* Set primary options (from S:.xfhrc.<unit>, if available). */
  125.  if (!InitOptions(glob))
  126.   {
  127.    returnpkt (pkt,DOSFALSE,ERROR_BAD_TEMPLATE,glob);
  128.    debug (("Error setting primary options - exiting.\n"));
  129.    ret=100;
  130.    goto exitthis;
  131.   }
  132.  
  133.  if (!InitXpk(glob))
  134.   {
  135.    returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
  136.    debug (("Error initialising Xpk routines - exiting.\n"));
  137.    ret=100;
  138.    goto exitthis;
  139.   }
  140.  
  141.  debug (("Using '%s' as root directory...\n",glob->xRootName));
  142.  glob->xprocid=DoDeviceProc( (LONG *)&glob->xrootlock,glob->xRootName,glob);
  143.  if (!glob->xprocid)
  144.   {
  145.    glob->xrootlock=0L;                      /* Don't xUnLock() */
  146.    returnpkt (pkt,DOSFALSE,ERROR_OBJECT_NOT_FOUND,glob);
  147.    ret=100;
  148.    debug (("Error doing DeviceProc(%s) - exiting.\n",glob->xRootName));
  149.    goto exitthis;
  150.   }
  151.  glob->xrootlock=b2c(glob->xrootlock);
  152.  debug (("DeviceProc(%s) returned: %lx %lx\n",glob->xRootName,
  153.          glob->xprocid,glob->xrootlock));
  154.  glob->xrootlock=xLock(glob,glob->xrootlock,glob->xRootName,ACCESS_READ);
  155.  if (glob->xrootlock==NULL)
  156.   {
  157.    returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
  158.    ret=100;
  159.    debug (("Error obtaining xrootlock: %ld - exiting.\n",glob->ioerr,
  160.            glob->xRootName));
  161.    goto exitthis;
  162.   }
  163.  debug (("Obtained xrootlock: %lx\n",glob->xrootlock ));
  164.  
  165.  if (!SetOptionsFromFile(glob,glob->xrootlock,ALTOPTIONPATH))
  166.   {
  167.    returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
  168.    ret=100;
  169.    debug (("Error setting secondary options.\n"));
  170.    goto exitthis;
  171.   }
  172.  
  173.  if (!xInfo(glob, glob->xrootlock,&glob->infodata))
  174.   {
  175.    returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
  176.    ret=100;
  177.    debug (("Error obtaining disk info: %ld\n",glob->ioerr));
  178.    goto exitthis;
  179.   }
  180.  glob->bytesperblock=glob->infodata.id_BytesPerBlock;
  181.    
  182.  if (parent=xParentDir(glob,glob->xrootlock)) xUnLock(glob,parent);
  183.  
  184.  if (!xExamine(glob,glob->xrootlock,&glob->fib1))
  185.   {
  186.    returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
  187.    ret=100;
  188.    debug (("Error finding name for volume: %ld\n",glob->ioerr));
  189.    goto exitthis;
  190.   }
  191.    
  192.  if (!(glob->rootlock=makerootlockdayone(glob)))
  193.   {
  194.    returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
  195.    ret=100;
  196.    debug (("Error creating rootlock: %ld - exiting.\n",glob->ioerr));
  197.    goto exitthis;
  198.   }
  199.    
  200.  if (!createvolnode(glob, parent == NULL, &glob->fib1))
  201.   {
  202.    returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
  203.    ret=100;
  204.    debug (("Error creating volume node - exiting.\n"));
  205.    goto exitthis;
  206.   }
  207.  
  208.  if (!InitArexx(glob))
  209.   {
  210.    returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
  211.    ret=100;
  212.    debug (("Error initialising AREXX stuff.\n"));
  213.    goto exitthis;
  214.   }
  215.  
  216.  if (!UpdateXFHNode(glob))
  217.   {
  218.    debug (("Error initialising XFHNode.\n"));
  219.    /* Carry on... */
  220.   }
  221.    
  222.  /* Handler opened succesfully. Patch in task address so that we will
  223.  * stay in control for all future references.
  224.  */
  225.  glob->devnode->dn_Task=glob->dosport;
  226.       
  227.  debug (("1: Packet type received: %lx\n",pkt->dp_Type));
  228.  returnpkt (pkt,DOSTRUE,0L,glob);
  229.  
  230.  glob->opencnt=0;        /* Just for good measure... */
  231.  /* Ready to go for the main loop.
  232.   * Lets pray that we get no new messages before the initial ReplyPkt()
  233.   * (otherwise we may loose the signal for the message port).
  234.   */
  235.  for (glob->done=FALSE; !glob->done;)
  236.   {
  237.    ULONG signals=Wait(arexxsigmask(glob)|getpktsigmask(glob)|guisigmask(glob));
  238.  
  239.    if (signals&arexxsigmask(glob)) checkarexxmsg(glob);
  240.    if (signals&guisigmask(glob))
  241.     if (!UpdateXFHNode(glob))
  242.      debug (("Error during UpdateXFHNode().\n"));
  243.  
  244.    if (signals&getpktsigmask(glob))
  245.     while (!glob->done&&(pkt=checkpkt(glob)))
  246.      handle_packet (glob,pkt);
  247.   }
  248.       
  249. exitthis:
  250.  debug (("CFS exiting...\n"));
  251.  CleanupArexx (glob);
  252.  if (glob->volnode) freevolnode (glob);
  253.  if (glob->rootlock) CFSUnLock (glob,glob->rootlock);
  254.  CleanupXpk (glob);
  255.  CleanupOptions (glob);
  256.  if (glob->ioport) DeletePort (glob->ioport);
  257.  if (glob->devname) freestr (glob->devname);
  258.    
  259. /*
  260.  * Unload the code. This is mostly to serve the ACTION_DIE packet.
  261.  * Useful for debugging (otherwise countless copies might end up in memory.
  262.  * It is rather ugly, however, and propably not really useful.
  263.  */
  264.  Forbid();
  265.  UnLoadSeg (glob->devnode->dn_SegList);
  266.  glob->devnode->dn_SegList=NULL;
  267.    
  268.  if (glob->DOSBase) CloseLibrary(glob->DOSBase);
  269.  FreeMem (glob,sizeof(struct glob));
  270.  
  271.  return ret;
  272. }
  273.  
  274. #ifndef ACTION_GET_DISK_FSSM
  275. #define ACTION_GET_DISK_FSSM 4201
  276. #endif
  277.  
  278. void handle_packet(glb glob,struct DosPacket *pkt)
  279.  
  280. {
  281.  glob->ioerr=0L;
  282.  switch(pkt->dp_Type)
  283.   {
  284.    case ACTION_LOCATE_OBJECT:
  285.     {
  286.      struct FileLock *mylock;
  287.      struct CFSLock *mycfslock;
  288.          
  289.      debug (("ACTION_LOCATE_OBJECT(%lx,\"%s\",%ld)",
  290.              pkt->dp_Arg1,
  291.              bstr2c(pkt->dp_Arg2,glob->debugbuf1),
  292.              pkt->dp_Arg3));
  293.      mylock=b2c(pkt->dp_Arg1);
  294.      mycfslock=mylock?(struct CFSLock *)mylock->fl_Key:glob->rootlock;
  295.      mycfslock=CFSLock(glob, 
  296.                        mycfslock,
  297.                        bstr2c(pkt->dp_Arg2,glob->pktstringbuf),
  298.                        pkt->dp_Arg3);
  299.      if (mycfslock)
  300.       if (mylock=CreateFileLock(glob,mycfslock)) glob->opencnt++;
  301.       else
  302.        {
  303.         LONG saveioerr;
  304.  
  305.         saveioerr=glob->ioerr;
  306.         CFSUnLock(glob, mycfslock);
  307.         glob->ioerr=saveioerr;
  308.        }
  309.      else mylock=NULL;
  310.  
  311.      debug (("=%lx\n",c2b(mylock)));
  312.      returnpkt (pkt,c2b(mylock),glob->ioerr,glob);
  313.      break;
  314.     }
  315.  
  316.    case ACTION_COPY_DIR:
  317.     {
  318.      struct FileLock *mylock;
  319.      struct CFSLock *mycfslock;
  320.         
  321.      debug (("ACTION_COPY_DIR(%lx)",pkt->dp_Arg1));
  322.      mylock=b2c(pkt->dp_Arg1);
  323.      mycfslock=mylock?(struct CFSLock *)mylock->fl_Key:glob->rootlock;
  324.      if (mycfslock=CFSDupLock(glob,mycfslock))
  325.       {
  326.        if (mylock=CreateFileLock(glob, mycfslock )) glob->opencnt++;
  327.        else
  328.         {
  329.          LONG saveioerr;
  330.  
  331.          saveioerr=glob->ioerr;
  332.          CFSUnLock(glob,mycfslock);
  333.          glob->ioerr=saveioerr;
  334.         }
  335.       }
  336.      else mylock=NULL;
  337.  
  338.      debug (("=%lx\n",c2b(mylock)));
  339.      returnpkt (pkt, c2b(mylock), glob->ioerr, glob);
  340.      break;
  341.     }
  342.  
  343.    case ACTION_PARENT:
  344.     {
  345.      struct FileLock *mylock;
  346.      struct CFSLock *mycfslock;
  347.  
  348.      debug (("ACTION_PARENT(%lx)",pkt->dp_Arg1));
  349.      mylock=b2c(pkt->dp_Arg1);
  350.      mycfslock=mylock?(struct CFSLock *)mylock->fl_Key:glob->rootlock;
  351.      if (mycfslock=CFSParentDir(glob,mycfslock))
  352.       {
  353.        if (mylock=CreateFileLock(glob,mycfslock)) glob->opencnt++;
  354.        else
  355.         {
  356.          LONG saveioerr;
  357.  
  358.          saveioerr=glob->ioerr;
  359.          CFSUnLock(glob, mycfslock);
  360.          glob->ioerr=saveioerr;
  361.         }
  362.       }
  363.      else mylock=NULL;
  364.  
  365.      debug (("=%lx\n",c2b(mylock)));
  366.      returnpkt (pkt, c2b(mylock), glob->ioerr, glob);
  367.      break;
  368.     }
  369.  
  370.    case ACTION_FREE_LOCK:
  371.     {
  372.      BOOL err;
  373.      struct FileLock *mylock;
  374.        
  375.      debug (("ACTION_FREE_LOCK(%lx)\n",pkt->dp_Arg1));
  376.      mylock=b2c(pkt->dp_Arg1);
  377.      if (mylock)
  378.       {
  379.        err=CFSUnLock(glob,(void *)mylock->fl_Key);
  380.        if (err)
  381.         {
  382.          dfree(mylock);
  383.          glob->opencnt--;
  384.         }
  385.       }
  386.      else err=ERROR_OBJECT_WRONG_TYPE;
  387.  
  388.      returnpkt (pkt,err,glob->ioerr,glob);
  389.      break;
  390.     }
  391.  
  392.    /* ToDo: Handle NULL locks correct (but what is correct?)
  393.     * Now, a NULL lock is equal to out root lock.
  394.     */
  395.    case ACTION_SAME_LOCK:
  396.     {
  397.      struct FileLock *fl1,*fl2;
  398.      BOOL res;
  399.        
  400.      fl1=b2c(pkt->dp_Arg1);
  401.      fl2=b2c(pkt->dp_Arg2);
  402.      debug (("ACTION_SAME_LOCK(%lx,%lx)",fl1,fl2));
  403.      /* ToDo: This bit tests that both locks belong to us - this
  404.       * is probably bogus.
  405.       */
  406.      if ((fl1!=NULL)&&(fl1->fl_Task!=glob->dosport)) res=FALSE;
  407.      else
  408.       if ((fl2!=NULL)&&(fl2->fl_Task!=glob->dosport)) res=FALSE;
  409.       else
  410.        {
  411.         struct CFSLock *f1,*f2;
  412.  
  413.         f1=fl1?(struct CFSLock *)fl1->fl_Key:glob->rootlock;
  414.         f2=fl2?(struct CFSLock *)fl2->fl_Key:glob->rootlock;
  415.         res=CFSSameLock(glob,f1,f2);
  416.        }
  417.  
  418.      debug (("=%ld\n",res));
  419.      /* ToDo: DOCS mention error code in case of zero return.
  420.       * Not currently implemented.
  421.       */
  422.      returnpkt (pkt,res,glob->ioerr,glob);
  423.      break;
  424.     }
  425.  
  426.    case ACTION_FINDINPUT:   /* (filehandle, lock, name)->BOOL */
  427.    case ACTION_FINDOUTPUT:
  428.    case ACTION_FINDUPDATE:
  429.     {
  430.      struct FileHandle *fh;
  431.      struct CFSFH *cfsfh;
  432.      char *name;
  433.      struct FileLock *parentlock;
  434.      struct CFSLock *cfsparentlock;
  435.       
  436.      debug (("%s(%lx,%lx,\"%s\")\n",
  437.             pkt->dp_Type==ACTION_FINDINPUT ?"ACTION_FINDINPUT": 
  438.             pkt->dp_Type==ACTION_FINDOUTPUT?"ACTION_FINDOUTPUT":
  439.                                             "ACTION_FINDUPDATE",
  440.             pkt->dp_Arg1,pkt->dp_Arg2,
  441.             bstr2c(pkt->dp_Arg3,glob->debugbuf1)));
  442.       
  443.      fh=b2c(pkt->dp_Arg1);
  444.      parentlock=b2c(pkt->dp_Arg2);
  445.      cfsparentlock=parentlock?(struct CFSLock *)parentlock->fl_Key:glob->rootlock;
  446.      name=bstr2c(pkt->dp_Arg3, glob->pktstringbuf);
  447.      cfsfh=CFSOpen(glob,cfsparentlock,name,pkt->dp_Type);
  448.      debug (("(=%lx)\n",cfsfh));
  449.      if (cfsfh)
  450.       {
  451.        glob->opencnt++;
  452.        fh->fh_Arg1=c2b(cfsfh);
  453.        returnpkt (pkt,DOSTRUE,glob->ioerr,glob);
  454.       }
  455.      else returnpkt (pkt,DOSFALSE,glob->ioerr,glob);
  456.      break;
  457.     }
  458.  
  459.    case ACTION_READ:    /* (fh->arg1, buf, len)->actlen */
  460.     {
  461.      struct CFSFH *cfsfh;
  462.      LONG len;
  463.      void *buf;
  464.          
  465.      debug (("ACTION_READ(%lx,%lx,%ld)\n",
  466.              pkt->dp_Arg1,pkt->dp_Arg2,pkt->dp_Arg3));
  467.      cfsfh=b2c(pkt->dp_Arg1);
  468.      buf=(void *)pkt->dp_Arg2;
  469.      len=pkt->dp_Arg3;
  470.      len=CFSRead(glob, cfsfh, buf, len);
  471.      returnpkt (pkt, len, glob->ioerr, glob);
  472.      break;
  473.     }
  474.  
  475.    case ACTION_WRITE:    /* (fh->arg1, buf, len)->actlen */
  476.     {
  477.      struct CFSFH *cfsfh;
  478.      LONG len;
  479.      void *buf;
  480.          
  481.      debug (("ACTION_WRITE(%lx,%lx,%ld)\n",
  482.              pkt->dp_Arg1,pkt->dp_Arg2,pkt->dp_Arg3));
  483.      cfsfh=b2c(pkt->dp_Arg1);
  484.      buf=(void *)pkt->dp_Arg2;
  485.      len=pkt->dp_Arg3;
  486.      len=CFSWrite(glob, cfsfh, buf, len);
  487.      debug (("ACTION_WRITE returns %ld %ld.\n",len, glob->ioerr));
  488.      returnpkt (pkt, len, glob->ioerr, glob);
  489.      break;
  490.     }
  491.  
  492.    case ACTION_SEEK:    /* (fh->arg1, pos, offset)->actlen */
  493.     {
  494.      struct CFSFH *cfsfh;
  495.      LONG pos;
  496.      LONG offset;
  497.          
  498.      debug (("ACTION_SEEK(%lx,%lx,%ld)\n",
  499.              pkt->dp_Arg1,pkt->dp_Arg2,pkt->dp_Arg3));
  500.      cfsfh=b2c(pkt->dp_Arg1);
  501.      pos=pkt->dp_Arg2;
  502.      offset=pkt->dp_Arg3;
  503.      pos=CFSSeek(glob, cfsfh, pos, offset);
  504.      returnpkt (pkt, pos, glob->ioerr, glob);
  505.      break;
  506.     }
  507.  
  508.    case ACTION_END:     /* (fh->arg1) -> BOOL */
  509.     {
  510.      struct CFSFH *cfsfh;
  511.      BOOL res;
  512.          
  513.      cfsfh=b2c(pkt->dp_Arg1);
  514.      debug (("ACTION_END(%lx)\n",cfsfh));
  515.      res=CFSClose( glob, cfsfh );
  516.      if (res ) glob->opencnt--;
  517.      debug (("Closing file - still %ld files open.\n",glob->opencnt));
  518.      returnpkt (pkt,res,pkt->dp_Res2,glob);
  519.      break;
  520.     }
  521.  
  522.    case ACTION_DIE:
  523.     debug (("ACTION_DIE()\n"));
  524.     Forbid();
  525.     if (!glob->opencnt)
  526.      {
  527.       glob->done=TRUE;
  528.       returnpkt (pkt,DOSTRUE,pkt->dp_Res2,glob);
  529.       glob->devnode->dn_Task=NULL;
  530.       debug (("No open files - Handler exiting.\n"));
  531.      }
  532.     else
  533.      {
  534.       returnpkt (pkt,DOSFALSE,ERROR_OBJECT_IN_USE,glob);
  535.       debug (("Cannot end yet - still %ld open files.\n",glob->opencnt));
  536.      }
  537.     Permit();
  538.     break;
  539.  
  540.    case ACTION_EXAMINE_OBJECT:
  541.     {
  542.      struct FileInfoBlock *fib;
  543.      struct FileLock *mylock;
  544.      BOOL err;
  545.          
  546.      debug (("ACTION_EXAMINE_OBJECT(%lx,%lx)\n",pkt->dp_Arg1,pkt->dp_Arg2));
  547.      mylock=b2c(pkt->dp_Arg1);
  548.      fib=b2c(pkt->dp_Arg2);
  549.      err=CFSExamine(glob,mylock?(struct CFSLock *)mylock->fl_Key:glob->rootlock,fib);
  550.      debug (("NAME: %s DirEntryType: %ld err: %ld\n",
  551.             fib->fib_FileName, fib->fib_DirEntryType,err));
  552.      cstr2binplace(&fib->fib_FileName[0]);
  553.      cstr2binplace(&fib->fib_Comment[0]);
  554.      returnpkt (pkt,err,glob->ioerr,glob);
  555.      break;
  556.     }
  557.  
  558.    case ACTION_EXAMINE_NEXT:
  559.     {
  560.      struct FileInfoBlock *fib;
  561.      struct FileLock *mylock;
  562.      BOOL err;
  563.          
  564.      debug (("ACTION_EXAMINE_NEXT(%lx,%lx)\n",pkt->dp_Arg1,pkt->dp_Arg2));
  565.      mylock=b2c(pkt->dp_Arg1);
  566.      fib=b2c(pkt->dp_Arg2);
  567.      bstr2cinplace (&fib->fib_FileName[0]);
  568.      safebstr2cinplace (&fib->fib_Comment[0],80);
  569.      err=CFSExamineNext(glob, 
  570.                         mylock?(struct CFSLock *)mylock->fl_Key:glob->rootlock,
  571.                         fib);
  572.      debug (("NAME: %s DirEntryType: %ld err: %ld\n",
  573.               fib->fib_FileName, fib->fib_DirEntryType,err));
  574.      cstr2binplace (&fib->fib_FileName[0]);
  575.      cstr2binplace (&fib->fib_Comment[0]);
  576.      returnpkt (pkt,err,glob->ioerr,glob);
  577.      break;
  578.     }
  579.  
  580.    case ACTION_CREATE_DIR:
  581.     { /* (parentlock, name) -> lock */
  582.      struct FileLock *mylock;
  583.      struct CFSLock *lock;
  584.  
  585.      debug (("ACTION_CREATE_DIR(%lx,\"%s\") ",
  586.              pkt->dp_Arg1,bstr2c(pkt->dp_Arg2,glob->debugbuf1)));
  587.      mylock=b2c(pkt->dp_Arg1);
  588.      lock=CFSCreateDir(glob, 
  589.                        mylock?(struct CFSLock *)mylock->fl_Key:glob->rootlock,
  590.                        bstr2c(pkt->dp_Arg2,glob->pktstringbuf));
  591.      if (lock)
  592.       {
  593.        if (mylock=CreateFileLock(glob,lock)) glob->opencnt++;
  594.        else
  595.         {
  596.          LONG saveioerr;
  597.  
  598.          saveioerr=glob->ioerr;
  599.          CFSUnLock (glob,lock);
  600.          glob->ioerr=saveioerr;
  601.         }
  602.       }
  603.      else mylock=NULL;
  604.  
  605.      debug (("= %lx\n",mylock));
  606.      returnpkt (pkt, c2b(mylock), glob->ioerr, glob);
  607.      break;
  608.     }
  609.  
  610.    case ACTION_DELETE_OBJECT:
  611.     { /* (parentlock, name) -> succes */
  612.      struct FileLock *mylock;
  613.      BOOL err;
  614.  
  615.      debug (("ACTION_DELETE_OBJECT(%lx,\"%s\")\n", pkt->dp_Arg1,
  616.              bstr2c(pkt->dp_Arg2,glob->debugbuf1)));
  617.      mylock=b2c(pkt->dp_Arg1);
  618.      err=CFSDeleteFile(glob,
  619.                        mylock?(struct CFSLock *)mylock->fl_Key:glob->rootlock,
  620.                        bstr2c(pkt->dp_Arg2,glob->pktstringbuf));
  621.      if (!err) debug (("Error deleting file!\n"));
  622.      returnpkt (pkt, err, glob->ioerr, glob);
  623.      break;
  624.     }
  625.  
  626.    case ACTION_RENAME_OBJECT:
  627.     { /* (lock1,name1,lock2,name2) -> succes */
  628.      struct FileLock *mylock1, *mylock2;
  629.      BOOL err;
  630.  
  631.      /* ToDo: Check that both locks belong to us? */
  632.      debug (("ACTION_RENAME_OBJECT(%lx,\"%s\", %lx,\"%s\")\n",pkt->dp_Arg1,
  633.              bstr2c(pkt->dp_Arg2,glob->debugbuf1),
  634.              pkt->dp_Arg3,
  635.              bstr2c(pkt->dp_Arg4,glob->debugbuf2)));
  636.      mylock1=b2c(pkt->dp_Arg1);
  637.      mylock2=b2c(pkt->dp_Arg3);
  638.  
  639.      err=CFSRename(glob,
  640.                    mylock1?(struct CFSLock *)mylock1->fl_Key:glob->rootlock,
  641.                    bstr2c(pkt->dp_Arg2,glob->pktstringbuf),
  642.                    mylock2?(struct CFSLock *)mylock2->fl_Key:glob->rootlock,
  643.                    bstr2c(pkt->dp_Arg4,glob->pktstringbuf2));
  644.      if (!err) debug (("Error renaming file!\n"));
  645.      returnpkt (pkt, err, glob->ioerr, glob);
  646.      break;
  647.     }
  648.  
  649.    case ACTION_SET_PROTECT:
  650.     { /* (dummy, parentlock, name, bits) -> succes */
  651.      struct FileLock *mylock;
  652.      BOOL err;
  653.  
  654.      debug (("ACTION_SET_PROTECT([%lx] %lx,\"%s\",%lx)\n",
  655.              pkt->dp_Arg1,pkt->dp_Arg2,
  656.              bstr2c(pkt->dp_Arg3,glob->debugbuf1),
  657.              pkt->dp_Arg4));
  658.      mylock=b2c(pkt->dp_Arg2);
  659.      err=CFSSetProtection(glob,
  660.                           mylock?(struct CFSLock *)mylock->fl_Key:glob->rootlock,
  661.                           bstr2c(pkt->dp_Arg3,glob->pktstringbuf),
  662.                           pkt->dp_Arg4);
  663.  
  664.      if (!err) debug (("Error changing protection bits!\n"));
  665.      returnpkt (pkt,err,glob->ioerr,glob);
  666.      break;
  667.     }
  668.  
  669.    case ACTION_SET_COMMENT:
  670.     { /* (dummy, parentlock, name, comment) -> succes */
  671.      struct FileLock *mylock;
  672.      BOOL err;
  673.  
  674.      debug (("ACTION_SET_COMMENT([%lx] %lx,\"%s\",\"%s\")\n",
  675.              pkt->dp_Arg1,pkt->dp_Arg2,
  676.              bstr2c(pkt->dp_Arg3,glob->debugbuf1),
  677.              bstr2c(pkt->dp_Arg4,glob->debugbuf2)));
  678.      mylock=b2c(pkt->dp_Arg2);
  679.      err=CFSSetComment(glob,
  680.                        mylock?(struct CFSLock *)mylock->fl_Key:glob->rootlock,
  681.                        bstr2c(pkt->dp_Arg3,glob->pktstringbuf),
  682.                        bstr2c(pkt->dp_Arg4,glob->pktstringbuf2));
  683.      if (!err) debug (("Error changing file comment!\n"));
  684.      returnpkt (pkt,err,glob->ioerr,glob);
  685.      break;
  686.     }
  687.  
  688.    case ACTION_SET_DATE:
  689.     { /* (dummy, parentlock, name, datestamp) -> succes */
  690.      struct FileLock *mylock;
  691.      BOOL err;
  692.  
  693.      debug (("ACTION_SET_DATE([%lx] %lx,\"%s\",%ld,%ld,%ld)\n",
  694.              pkt->dp_Arg1,pkt->dp_Arg2,
  695.              bstr2c(pkt->dp_Arg3,glob->debugbuf1),
  696.              ((struct DateStamp *)(pkt->dp_Arg4))->ds_Days,
  697.              ((struct DateStamp *)(pkt->dp_Arg4))->ds_Minute,
  698.              ((struct DateStamp *)(pkt->dp_Arg4))->ds_Tick));
  699.      mylock=b2c(pkt->dp_Arg2);
  700.      err=CFSSetDate(glob,
  701.                     mylock?(struct CFSLock *)mylock->fl_Key:glob->rootlock,
  702.                     bstr2c(pkt->dp_Arg3,glob->pktstringbuf),
  703.                     (struct DateStamp *)pkt->dp_Arg4);
  704.      if (!err) debug (("Error changing objects date!\n"));
  705.      returnpkt (pkt, err, glob->ioerr, glob);
  706.      break;
  707.     }
  708.  
  709.    case ACTION_DISK_INFO:
  710.     /* (infodata)=BOOL */
  711.     debug (("ACTION_DISK_INFO(%lx)\n",pkt->dp_Arg1));
  712.     returnpkt (pkt,diskinfo(glob,b2c(pkt->dp_Arg1)),0L,glob);
  713.     break;
  714.  
  715.    case ACTION_INFO:
  716.     /* (lock,infodata)=BOOL */
  717.     debug (("ACTION_INFO(%lx,%lx)\n",pkt->dp_Arg1,pkt->dp_Arg2));
  718.     returnpkt (pkt,diskinfo(glob,b2c(pkt->dp_Arg2)),0L,glob);
  719.     break;
  720.  
  721.    case ACTION_RENAME_DISK:
  722.     {  /* (BCPLNAME)=BOOL */
  723.      BOOL res;
  724.  
  725.      debug (("ACTION_RENAME_DISK(%s)\n",
  726.              bstr2c(pkt->dp_Arg1,glob->debugbuf1)));
  727.      res=SetOptionPermanent(glob, "VOLUMENAME",
  728.                             bstr2c(pkt->dp_Arg1,glob->pktstringbuf));
  729.      if (!res) debug (("Error during relabel: %ld.\n",glob->ioerr));
  730.      returnpkt (pkt,res,glob->ioerr,glob);
  731.      break;
  732.     }
  733.  
  734.    case ACTION_IS_FILESYSTEM:
  735.     debug (("ACTION_IS_FILESYSTEM\n"));
  736.     returnpkt (pkt,DOSTRUE,0L,glob);
  737.     break;
  738.  
  739.    case ACTION_PARENT_FH:
  740.     {
  741.      struct FileLock *mylock;
  742.      struct CFSLock *mycfslock;
  743.          
  744.      debug (("ACTION_PARENT_FH(%lx)",pkt->dp_Arg1));
  745.      if (mycfslock=CFSParentFH(glob,b2c(pkt->dp_Arg1)))
  746.       if (mylock=CreateFileLock(glob, mycfslock )) glob->opencnt++;
  747.       else
  748.        {
  749.         LONG saveioerr;
  750.  
  751.         saveioerr=glob->ioerr;
  752.         CFSUnLock (glob,mycfslock);
  753.         glob->ioerr=saveioerr;
  754.         }
  755.       else mylock=NULL;
  756.  
  757.      debug (("=%lx\n",c2b(mylock)));
  758.      returnpkt (pkt, c2b(mylock), glob->ioerr, glob);
  759.      break;
  760.     }
  761.  
  762.    case ACTION_EXAMINE_FH:
  763.     {
  764.      struct FileInfoBlock *fib;
  765.      struct CFSFH *fh;
  766.      BOOL err;
  767.          
  768.      debug (("ACTION_EXAMINE_FH(%lx,%lx)\n",pkt->dp_Arg1,pkt->dp_Arg2));
  769.      fh=b2c(pkt->dp_Arg1);
  770.      fib=b2c(pkt->dp_Arg2);
  771.      err=CFSExamineFH(glob, fh, fib);
  772.      debug (("NAME: %s DirEntryType: %ld err: %ld\n",
  773.              fib->fib_FileName, fib->fib_DirEntryType,err));
  774.      cstr2binplace (&fib->fib_FileName[0]);
  775.      cstr2binplace (&fib->fib_Comment[0]);
  776.      returnpkt (pkt,err,glob->ioerr,glob);
  777.      break;
  778.     }
  779.  
  780.    case ACTION_MAKE_LINK:
  781.     {
  782.      struct FileLock *mylock;
  783.      BOOL succ;
  784.  
  785.      debug (("ACTION_MAKE_LINK(%lx,\"%s\",%lx,%ld)\n",
  786.              pkt->dp_Arg1,bstr2c(pkt->dp_Arg2,glob->debugbuf1),
  787.              pkt->dp_Arg3,pkt->dp_Arg4));
  788.  
  789.      mylock=b2c(pkt->dp_Arg1);
  790.      succ=CFSMakeLink(glob,
  791.                       mylock?(struct CFSLock *)mylock->fl_Key:glob->rootlock,
  792.                       bstr2c(pkt->dp_Arg2,glob->pktstringbuf),
  793.                       pkt->dp_Arg3,pkt->dp_Arg4);
  794.  
  795. #ifdef DEBUG
  796.      if (!succ) debug (("Error making link!\n"));
  797. #endif
  798.  
  799.      returnpkt (pkt,succ,glob->ioerr,glob);
  800.      break;
  801.     }
  802.  
  803.    case ACTION_READ_LINK:
  804.     {
  805.      struct FileLock *mylock;
  806.      BOOL succ;
  807.  
  808.      debug (("ACTION_READ_LINK(%lx,\"%s\")\n",pkt->dp_Arg1,pkt->dp_Arg2));
  809.  
  810.      mylock=b2c(pkt->dp_Arg1);
  811.      succ=CFSReadLink(glob,
  812.                       mylock?(struct CFSLock *)mylock->fl_Key:glob->rootlock,
  813.                       (char *)pkt->dp_Arg2,(char *)pkt->dp_Arg3,pkt->dp_Arg4);
  814.  
  815. #ifdef DEBUG
  816.      if (succ) debug (("ReadLink: \"%s\"\n",pkt->dp_Arg3));
  817. #endif
  818.  
  819.      returnpkt (pkt,succ,glob->ioerr,glob);
  820.      break;
  821.     }
  822.  
  823.    case ACTION_GET_DISK_FSSM:
  824.     returnpkt (pkt,DOSFALSE,ERROR_OBJECT_WRONG_TYPE,glob);
  825.     break;
  826.  
  827.    default:
  828.     debug (("Unknown packet received: %ld\n",pkt->dp_Type));
  829.     returnpkt (pkt,DOSFALSE,ERROR_ACTION_NOT_KNOWN,glob);
  830.   }
  831. }
  832.  
  833. struct DosPacket *getpkt(glb glob)
  834.  
  835. {
  836.  struct Message *msg;
  837.    
  838.  while (!(msg=GetMsg(glob->dosport))) WaitPort(glob->dosport);
  839.  return (struct DosPacket *)msg->mn_Node.ln_Name;
  840. }
  841.  
  842.  
  843. ULONG getpktsigmask(glb glob)
  844.  
  845. {
  846.  return (ULONG)(1L<<glob->dosport->mp_SigBit);
  847. }
  848.  
  849.  
  850. struct DosPacket *checkpkt(glb glob)
  851.  
  852. {
  853.  struct Message *msg;
  854.    
  855.  if (msg=GetMsg(glob->dosport)) return (struct DosPacket *)msg->mn_Node.ln_Name;
  856.  else return NULL;
  857. }
  858.  
  859.  
  860. void returnpkt (struct DosPacket *pkt,LONG res1,LONG res2,glb glob)
  861.  
  862. {
  863.  struct MsgPort *port;
  864.  struct Message *msg;
  865.    
  866.  port=pkt->dp_Port;
  867.  msg=pkt->dp_Link;
  868.  
  869.  msg->mn_Node.ln_Succ=msg->mn_Node.ln_Pred=NULL;
  870.  msg->mn_Node.ln_Name=(char *)pkt;
  871.    
  872.  pkt->dp_Res1=res1;
  873.  pkt->dp_Res2=res2;
  874.  pkt->dp_Port=glob->dosport;
  875.    
  876.  PutMsg(port,msg);
  877. }
  878.  
  879. struct devprocmsg
  880.  
  881. {
  882.  struct Message msg;
  883.  void (*func)();
  884.  char *filedesc;
  885.  struct MsgPort *procid;
  886.  LONG res2;
  887. };
  888.  
  889. void __asm CallDeviceProc(register __a0 struct devprocmsg *msg)
  890.  
  891. {
  892.  msg->procid=DeviceProc(msg->filedesc);
  893.  msg->res2=IoErr();
  894. }
  895.  
  896. struct MsgPort *DoDeviceProc(LONG *res2,char *filedesc,glb glob)
  897.  
  898. {
  899.  struct devprocmsg msg,*msg2;
  900.  extern void DoDOSSeg();
  901.  struct MsgPort *procid;
  902.    
  903.  msg.msg.mn_Node.ln_Succ=NULL;
  904.  msg.msg.mn_Node.ln_Pred=NULL;
  905.  msg.msg.mn_Node.ln_Name=NULL;
  906.  msg.msg.mn_Node.ln_Type=NT_MESSAGE;
  907.  msg.msg.mn_Node.ln_Pri=0;
  908.  msg.msg.mn_ReplyPort=glob->ioport;
  909.  msg.msg.mn_Length=sizeof(msg);
  910.  msg.func=(void (*)())CallDeviceProc;
  911.  msg.filedesc=filedesc;
  912.    
  913.  if (!(procid=CreateProc("DoDOS",glob->mytask->tc_Node.ln_Pri,
  914.                          (BPTR)((ULONG)DoDOSSeg>>2),4000L))) return 0L;
  915.    
  916.  PutMsg(procid,(struct Message *)&msg);
  917.  do WaitPort(glob->ioport);
  918.  while (!(msg2=(struct devprocmsg *)GetMsg(glob->ioport)));
  919.  
  920. #ifdef DEBUG
  921.  if (msg2!=&msg) KPrintF ("ERROR: bogus return message: &msg=%lx msg2=%lx\n",&msg,msg2);
  922. #endif
  923.  if (res2) *res2=msg2->res2;
  924.  return msg2->procid;
  925. }
  926.  
  927. /* DOS device list locking.
  928.  * ToDo: Use correct 2.0 locking calls.
  929.  */
  930.  
  931. static void MyLockDosList(glb glob)
  932.  
  933. {
  934.  Forbid();
  935. }
  936.  
  937. static void MyUnlockDosList(glb glob)
  938.  
  939. {
  940.  Permit();
  941. }
  942.  
  943.  
  944. void addvolnode(glb glob,struct DeviceList *volnode)
  945.  
  946. {
  947.  struct DosInfo *dosinfo;
  948.  
  949.  MyLockDosList(glob);
  950.  dosinfo=b2c( ((struct RootNode *)DOSBase->dl_Root)->rn_Info);
  951.  volnode->dl_Next=dosinfo->di_DevInfo;
  952.  dosinfo->di_DevInfo=c2b(volnode);
  953.  MyUnlockDosList(glob);
  954. }
  955.  
  956. BOOL removevolnode(glb glob,struct DeviceList *volnode)
  957.  
  958. {
  959.  struct DosInfo *dosinfo;
  960.  BPTR *p;
  961.    
  962.  /* ToDo: check for 2.0 device list locking. */
  963.  MyLockDosList(glob);
  964.  dosinfo=b2c( ((struct RootNode *)DOSBase->dl_Root)->rn_Info);
  965.  p=&dosinfo->di_DevInfo;
  966.    
  967.  while(*p)
  968.   if (b2c(*p) == volnode)
  969.    {
  970.     *p=volnode->dl_Next;
  971.     MyUnlockDosList(glob);
  972.     return TRUE;
  973.    }
  974.   else p=&( ((struct DeviceList *)b2c(*p)) -> dl_Next);
  975.  
  976.  MyUnlockDosList(glob);
  977.  /* Hey - we didn't find the node in the list! */
  978.  debug (("WARNING!:removevolnode(): volume node not found.\n"));
  979.  return FALSE;
  980. }
  981.  
  982. /* Used to update the 'Startup' field in our device node (used in option
  983.  * 'KILLSTARTUP').
  984.  */
  985.  
  986. void DevNode_Stuff_Startup_String(glb glob,BSTR value)
  987.  
  988. {
  989.  MyLockDosList(glob);
  990.  glob->devnode->dn_Startup=value;
  991.  MyUnlockDosList (glob);
  992. }
  993.  
  994.  
  995. /* NOTE: this function assumes properly dos device list locking!
  996.  * This function will fail if 'name' is NULL.
  997.  * NOTE: createvolnode(), below does this in it's own way.
  998.  */
  999. static BOOL stuffvolnamevolnode(glb glob,char *name)
  1000.  
  1001. {
  1002.  UBYTE *bcplname,*oldbcplname;
  1003.  
  1004.  /* NASTY BUG: It seems that the volume name is expected to be zero 
  1005.   * terminated even though it is a BSTR. Hence strlen()+2 in alloc. */
  1006.  /* Check if user specified a volume name. */
  1007.  
  1008.   if (name)
  1009.    {
  1010.     if (!(bcplname=dosalloc(strlen(name)+2)))
  1011.      {
  1012.       OUTOFMEM;
  1013.       return FALSE;
  1014.      }
  1015.     /* Free any old name. */
  1016.     oldbcplname=b2c(glob->volnode->dl_Name);
  1017.     if (oldbcplname) dosfree (oldbcplname);
  1018.  
  1019.    strcpy(bcplname,name);
  1020.    cstr2binplace(bcplname);
  1021.    glob->volnode->dl_Name=c2b(bcplname);
  1022.    debug (("Using user suplied volumename '%s'.\n",bcplname+1));
  1023.    return TRUE;
  1024.   }
  1025.  else
  1026.   {
  1027.    glob->ioerr=ERROR_INVALID_COMPONENT_NAME;
  1028.    return FALSE;
  1029.   }
  1030. }
  1031.  
  1032.  
  1033. /* This function creates our volumenode. The argument 'fixroot' is
  1034.  * a hack, telling whether the volumename should be changed to prevent
  1035.  * name-clashing with the volume name of the UFS.
  1036.  */
  1037. BOOL createvolnode(glb glob,BOOL fixroot,struct FileInfoBlock *fib)
  1038.  
  1039. {
  1040.  UBYTE *bcplname;
  1041.  
  1042.  if (!dalloc(glob->volnode)) return FALSE;
  1043.  
  1044.  /* NASTY BUG: It seems that the volume name is expected to be zero 
  1045.   * terminated even though it is a BSTR. Hence strlen()+2 in alloc. */
  1046.  /* Check if user specified a volume name. */
  1047.  
  1048.  if (glob->uservolname)
  1049.   {
  1050.    if (!(bcplname=dosalloc(strlen(glob->uservolname)+2)))
  1051.     {
  1052.      dfree(glob->volnode);
  1053.      return FALSE;
  1054.     }
  1055.  
  1056.    (void)strcpy(bcplname,glob->uservolname);
  1057.    debug (("Using user suplied volumename '%s'.\n",bcplname));
  1058.   }
  1059.  else
  1060.   {
  1061.    if (!(bcplname=dosalloc(strlen(fib->fib_FileName)+2+
  1062.                            (fixroot?strlen(XROOTNAME)+1:0))))
  1063.     {
  1064.      dfree(glob->volnode);
  1065.      return FALSE;
  1066.     }
  1067.  
  1068.    (void)strcat(strcpy(bcplname,fixroot?XROOTNAME "_":""),&fib->fib_FileName[0]);
  1069.    debug (("Using default volume name '%s'.\n",bcplname));
  1070.   }
  1071.    
  1072.  glob->volnode->dl_Type=DLT_VOLUME;
  1073.  glob->volnode->dl_Task=glob->dosport;
  1074.  glob->volnode->dl_Lock=c2b(NULL);
  1075.  glob->volnode->dl_VolumeDate=fib->fib_Date;
  1076.  glob->volnode->dl_LockList=c2b(NULL);
  1077.  glob->volnode->dl_DiskType=ID_DOS_DISK; /*Wonder what would be right*/
  1078.  glob->volnode->dl_unused=0L;
  1079.  cstr2binplace (bcplname);
  1080.  glob->volnode->dl_Name=c2b(bcplname);
  1081.    
  1082.  /* Check if user requested that we create a volume node. */
  1083.  /* if (glob->createvolnode) */
  1084.  addvolnode (glob,glob->volnode);
  1085.  
  1086.  return TRUE;
  1087. }
  1088.  
  1089. /* Set the volume name in the volnode. */
  1090. BOOL SetVolumeNameVolNode(glb glob,char *name)
  1091.  
  1092. {
  1093.  BOOL res;
  1094.  
  1095.  MyLockDosList(glob);
  1096.  res=stuffvolnamevolnode(glob,name);
  1097.  MyUnlockDosList(glob);
  1098.  return res;
  1099. }
  1100.  
  1101. BOOL freevolnode(glb glob)
  1102.  
  1103. {
  1104. /* Check if user requested that we create a volume node. */
  1105. /* if (glob->createvolnode)*/
  1106.  if (!removevolnode(glob,glob->volnode)) return FALSE;
  1107.  
  1108.  dosfree (b2c(glob->volnode->dl_Name));
  1109.  dfree (glob->volnode);
  1110.  
  1111.  return TRUE;
  1112. }
  1113.  
  1114.  
  1115. BOOL diskinfo(glb glob,struct InfoData *infodata)
  1116.  
  1117. {
  1118.  if (!xInfo(glob,glob->xrootlock,infodata))
  1119.   {
  1120.    debug (("Error: diskinfo(): xInfo() returned zero (%ld).\n",glob->ioerr));
  1121.    return DOSFALSE;
  1122.   }
  1123.  
  1124. /*   infodata->id_NumSoftErrors=0;*/
  1125. /*   infodata->id_UnitNumber=glob->fsstartup ?*/
  1126. /*                             glob->fsstartup->fssm_Unit : 0;*/
  1127. /*   infodata->id_DiskState=ID_VALIDATED;*/
  1128. /*   infodata->id_NumBlocks=1;*/
  1129. /*   infodata->id_NumBlocksUsed=1;*/
  1130. /*   infodata->id_BytesPerBlock=1;*/
  1131. /*   infodata->id_DiskType=ID_DOS_DISK;*/
  1132.  
  1133.  infodata->id_VolumeNode=c2b(glob->volnode);
  1134.  infodata->id_InUse=glob->opencnt?1:0;
  1135.  debug (("diskinfo(): U=%ld DS=%lx #=%ld #u=%ld #b=%ld IU=%ld.\n",
  1136.          infodata->id_UnitNumber,infodata->id_DiskState,infodata->id_NumBlocks,
  1137.          infodata->id_NumBlocksUsed,infodata->id_BytesPerBlock,
  1138.          infodata->id_InUse));
  1139.  
  1140.  return DOSTRUE;
  1141. }
  1142.  
  1143. UWORD PutChar[2] = {0x16C0,0x4E75};
  1144.  
  1145. /* dirty hack to avoid assembler part :-)
  1146.  
  1147.    16C0: move.b d0,(a3)+
  1148.    4E75: rts
  1149. */
  1150.  
  1151. void SPrintF(char *Buffer,char *FormatString,...)
  1152.  
  1153. {
  1154.  RawDoFmt (FormatString,(APTR)((LONG *)&FormatString+1L),(void *)PutChar,Buffer);
  1155. }
  1156.  
  1157. /* End of CFS.c */
  1158.